package de.slothsoft.wasbinich.swingclient.common;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JLabel;
import javax.swing.Timer;
import javax.swing.event.EventListenerList;

public class TimerControl extends JLabel implements ActionListener {

    private static final long serialVersionUID = 8190242634816059191L;
    public static final String COMMAND_ID = "timer target reached";

    public static final int TIME_SECOND = 1000;

    public static TimerControl createCountDown(int startCounter) {
	return new TimerControl(true, startCounter, 0);
    }

    public static TimerControl createCounter(int startCounter, int targetCounter) {
	return new TimerControl(false, startCounter, targetCounter);
    }

    protected final Timer timer;
    protected final EventListenerList listenerList = new EventListenerList();

    private boolean countDown;
    private int startCounter;
    private int targetCounter;

    private int counter;

    private String displayPattern = "{0}";

    public TimerControl(boolean countDown, int startCounter, int targetCounter) {
	this.countDown = countDown;
	this.startCounter = startCounter;
	this.targetCounter = targetCounter;
	this.timer = new Timer(0, this);
    }

    @Override
    public void actionPerformed(ActionEvent e) {
	tickCounter();
	setText("" + this.counter);
    }

    protected void tickCounter() {
	if (this.countDown) {
	    this.counter--;
	} else {
	    this.counter++;
	}
	if (this.counter == this.targetCounter) {
	    fireActionPerformed(new ActionEvent(this, ActionEvent.ACTION_PERFORMED, COMMAND_ID));
	    stop();
	}
    }

    /**
     * Adds an action listener to the <code>Timer</code>.
     * 
     * @param listener
     *            the listener to add
     * 
     * @see #Timer
     */
    public void addActionListener(ActionListener listener) {
	this.listenerList.add(ActionListener.class, listener);
    }

    /**
     * Removes the specified action listener from the <code>Timer</code>.
     * 
     * @param listener
     *            the listener to remove
     */
    public void removeActionListener(ActionListener listener) {
	this.listenerList.remove(ActionListener.class, listener);
    }

    /**
     * Returns an array of all the action listeners registered on this timer.
     * 
     * @return all of the timer's <code>ActionListener</code>s or an empty array
     *         if no action listeners are currently registered
     * 
     * @see #addActionListener
     * @see #removeActionListener
     * 
     * @since 1.4
     */
    public ActionListener[] getActionListeners() {
	return this.listenerList.getListeners(ActionListener.class);
    }

    /**
     * Notifies all listeners that have registered interest for notification on
     * this event type.
     * 
     * @param e
     *            the action event to fire
     * @see EventListenerList
     */
    protected void fireActionPerformed(ActionEvent e) {
	// Guaranteed to return a non-null array
	Object[] listeners = this.listenerList.getListenerList();

	// Process the listeners last to first, notifying
	// those that are interested in this event
	for (int i = listeners.length - 2; i >= 0; i -= 2) {
	    if (listeners[i] == ActionListener.class) {
		((ActionListener) listeners[i + 1]).actionPerformed(e);
	    }
	}
    }

    public void start() {
	if (this.timer.isRunning()) {
	    stop();
	}
	this.counter = this.startCounter;
	this.timer.start();
    }

    public void stop() {
	this.timer.stop();
    }

    public Timer getTimer() {
	return this.timer;
    }

    public boolean isCountDown() {
	return this.countDown;
    }

    public void setCountDown(boolean countDown) {
	this.countDown = countDown;
    }

    public int getStartCounter() {
	return this.startCounter;
    }

    public void setStartCounter(int startCounter) {
	this.startCounter = startCounter;
    }

    public int getTargetCounter() {
	return this.targetCounter;
    }

    public void setTargetCounter(int targetCounter) {
	this.targetCounter = targetCounter;
    }

    public void setDisplayPattern(String displayPattern) {
	this.displayPattern = displayPattern;
    }

    public String getDisplayPattern() {
	return this.displayPattern;
    }

}
